package pers.cz.quartz.job;

import cn.hutool.core.date.DateUtil;
import pers.cz.mapper.TaskJobMapper;
import pers.cz.model.TaskJob;
import pers.cz.quartz.core.QuartzJobFactory;
import pers.cz.spring.SpringContextUtil;
import pers.cz.websocket.MessagePushSocketUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * job监听
 * @program: PostGirl-panent
 * @description: ListenerThead
 * @author: Cheng Zhi
 * @create: 2021-07-25 22:06
 **/

public class ListenerThead extends Thread{

    Logger logger = LoggerFactory.getLogger(ListenerThead.class);

    private volatile Boolean flag = false;

    private String jobName; // 任务名

    private Long jobId; // 任务Id

    private Long timeOut; // 预计执行时长

    private JedisPool jedisPool;

    public ListenerThead(Long jobId, Long timeOut, String jobName) {
        this.jobId = jobId;
        this.timeOut = timeOut;
        this.jobName = jobName;
        this.jedisPool = SpringContextUtil.getBean(JedisPool.class);
        this.setDaemon(true); // 将线程设置为守护线程
    }

    public synchronized void stopThread(){
        logger.info(jobId + "监听线程即将销毁");
        flag = true;
    }

    @Override
    public void run() {
        String progress = "0";
        try {
            Long startTime = System.currentTimeMillis(); // ms

            Long timeOuts = timeOut*1000; // 将单位秒转换为ms

            String lastParcentage = "0";
            while (!flag) {

                Long currentTime = System.currentTimeMillis(); // ms
                // 如果开始时间和当前时间一样，则跳过本次计算
                if (startTime.equals(currentTime)) {
                    continue;
                }
                long cont = currentTime - startTime;
                if (cont > timeOuts) {
                    progress = "99";
                } else {
                    Long percentage = ((timeOuts - cont) / cont) * 100;
                    progress = getPercentage(cont, timeOuts);
                }
                // 为了避免频繁写入redis,当前值和上一次的值做对比，如果不同再写入redis
                if (progress.equals(lastParcentage)) {
                    continue;
                }

                lastParcentage = progress;
                String message = "schedule|" + this.jobId + "|" + progress;
                MessagePushSocketUtils.sendInfo(message, 0); // 广播消息
                // updateJobProgress(this.jobId, progress, resource); // 更新redis
            }

            // 当跳出循环时，表示要么执行完成，要么执行失败，将数据写入到数据库保存
            //String triggerState = QuartzJobFactory.getTriggerState(jobName);
            //Integer type = stateMapping(triggerState);
            Integer type = 1;
            // 更新最终结果到redis
            // updateJobProgress(this.jobId, progress, resource);
            progress = "100";
            String message = "schedule|" + this.jobId + "|" + progress;
            MessagePushSocketUtils.sendInfo(message, 0); // 广播消息

            this.updateJobType(type,progress); // 写入数据库
        } finally {
            //this.jedisPool.close();
        }
    }

    /**
     * 更新执行进度到redis中
     * @param jobId
     * @param progress
     */
    private void updateJobProgress(Long jobId, String progress, Jedis resource) {

        String hashKey = "progress";

        Map map = new HashMap();
        map.put(String.valueOf(jobId),progress);
        resource.hmset(hashKey, map);
    }
    /**
     * job状态与前台展示映射关系
     * @param triggerState
     * @return
     */
    private Integer stateMapping(String triggerState) {

        switch (triggerState) {

            case "NORMAL":
                return 1; // 处理中/正常

            case "PAUSED":
                return 0; // 未开始/暂停

            case "COMPLETE":
                return 4; // 处理成功/完成

            case "ERROR":
                return 3; // 处理存在异常/错误

            default :
                return 2; // 其余情况都视为失败
        }
    }

    /**
     * 更新数据库
     * @param schedule
     * @param progress
     */
    private void updateJobType(int schedule, String progress) {

        String triggerState = QuartzJobFactory.getTriggerState(jobName);
        Integer type = stateMapping(triggerState);

        TaskJob taskJob = new TaskJob();
        taskJob.setId(jobId);
        taskJob.setType(type);
        taskJob.setCreatedTime(DateUtil.date());
        if (type == 1) {
            taskJob.setSchedule(Integer.valueOf(progress));
        } else if (type == 4) {
            taskJob.setSchedule(100);
        }
        SpringContextUtil.getBean(TaskJobMapper.class).updateByPrimaryKeySelective(taskJob);
    }

    /**
     * 计算执行进度的百分比
     * @param cont
     * @param timeOut
     * @return
     */
    private String getPercentage(Long cont, Long timeOut) {

        java.text.NumberFormat numberformat=java.text.NumberFormat.getInstance();

        //设置精确到小数点后0位,也就是取整
        numberformat.setMaximumFractionDigits(0);

        String result = numberformat.format((float)cont/(float)timeOut*100);

        return result;
    }

}
